package com.thinkit.directive.render;
import com.thinkit.directive.emums.LangEnum;
import com.thinkit.utils.utils.Checker;
import freemarker.ext.beans.BeanModel;
import freemarker.template.*;
import java.util.*;

public class MethodWrapper {

    protected static TemplateModel getModel(int index, List<TemplateModel> arguments) {
        if (Checker.BeNotEmpty(arguments) && index < arguments.size()) {
            return arguments.get(index);
        }
        return null;
    }

    protected static <T> T getParam(int index, List<TemplateModel> arguments, LangEnum langEnum) throws TemplateModelException {
        TemplateModel templateModel = getModel(index,arguments);
        if(Checker.BeNotNull(templateModel)){
            Object value=null;
            switch (langEnum){
                case STRING:
                    value = toString(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case BOOLEAN:
                    value = toBoolean(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case INTEGER:
                    value = toInteger(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case LONG:
                    value = toLong(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case SHORT:
                    value = toShort(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case DOUBLE:
                    value = toDouble(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case DATE:
                    value = toDate(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case BEAN:
                    value = toBean(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case STRING_ARRAY:
                    value = toStringArray(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case MAP:
                    value = toMap(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case INTEGER_ARRAY:
                    value = toIntegerArray(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
                case LONG_ARRAY:
                    value = toLongArray(templateModel);
                    if(Checker.BeNotNull(value)){
                        return (T) value;
                    }
                    break;
            }
            return null;
        }
        return null;
    }

    private static String toString(TemplateModel templateModel) throws TemplateModelException {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateSequenceModel) {
                toString(((TemplateSequenceModel) templateModel).get(0));
            }
            if (templateModel instanceof TemplateScalarModel) {
                return ((TemplateScalarModel) templateModel).getAsString();
            } else if ((templateModel instanceof TemplateNumberModel)) {
                Number number = ((TemplateNumberModel) templateModel).getAsNumber();
                if(Checker.BeNotNull(number)){
                    return number.toString();
                }
                return null;
            }
        }
        return null;
    }

    private static Short toShort(TemplateModel templateModel) throws TemplateModelException {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateSequenceModel) {
                templateModel = ((TemplateSequenceModel) templateModel).get(0);
            }
            if (templateModel instanceof TemplateNumberModel) {
                Number number = ((TemplateNumberModel) templateModel).getAsNumber();
                if(Checker.BeNotNull(number)){
                    return number.shortValue();
                }
            } else if (templateModel instanceof TemplateScalarModel) {
                String strValue = ((TemplateScalarModel) templateModel).getAsString();
                if (Checker.BeNotBlank(strValue)) {
                    return Short.valueOf(strValue);
                }
            }
        }
        return null;
    }

    public static Long toLong(TemplateModel templateModel) throws TemplateModelException {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateSequenceModel) {
                templateModel = ((TemplateSequenceModel) templateModel).get(0);
            }
            if (templateModel instanceof TemplateNumberModel) {
                Number number = ((TemplateNumberModel) templateModel).getAsNumber();
                if(Checker.BeNotNull(number)){
                    return number.longValue();
                }
            } else if (templateModel instanceof TemplateScalarModel) {
                String strValue = ((TemplateScalarModel) templateModel).getAsString();
                if (Checker.BeNotBlank(strValue)) {
                    return Long.valueOf(strValue);
                }
            }
        }
        return null;
    }

    public static Integer toInteger(TemplateModel templateModel) throws TemplateModelException {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateSequenceModel) {
                toInteger(((TemplateSequenceModel) templateModel).get(0));
            }
            if (templateModel instanceof TemplateNumberModel) {
                Number number = ((TemplateNumberModel) templateModel).getAsNumber();
                if(Checker.BeNotNull(number)){
                    return number.intValue();
                }
            } else if (templateModel instanceof TemplateScalarModel) {
                String strValue = ((TemplateScalarModel) templateModel).getAsString();
                if (Checker.BeNotBlank(strValue)) {
                    return Integer.valueOf(strValue);
                }
            }
        }
        return null;
    }

    public static Double toDouble(TemplateModel templateModel) throws TemplateModelException {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateSequenceModel) {
                toDouble(((TemplateSequenceModel) templateModel).get(0));
            }
            if (templateModel instanceof TemplateNumberModel) {
                Number number = ((TemplateNumberModel) templateModel).getAsNumber();
                if(Checker.BeNotNull(number)){
                    return number.doubleValue();
                }
            } else if (templateModel instanceof TemplateScalarModel) {
                String s = ((TemplateScalarModel) templateModel).getAsString();
                if (Checker.BeNotBlank(s)) {
                   return Double.valueOf(s);
                }
            }
        }
        return null;
    }

    public static Boolean toBoolean(TemplateModel templateModel) throws TemplateModelException {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateSequenceModel) {
                templateModel = ((TemplateSequenceModel) templateModel).get(0);
            }
            if (templateModel instanceof TemplateBooleanModel) {
                return ((TemplateBooleanModel) templateModel).getAsBoolean();
            } else if (templateModel instanceof TemplateNumberModel) {
                return !(0 == ((TemplateNumberModel) templateModel).getAsNumber().intValue());
            } else if (templateModel instanceof TemplateScalarModel) {
                String temp = ((TemplateScalarModel) templateModel).getAsString();
                if (Checker.BeNotBlank(temp)) {
                    return Boolean.valueOf(temp);
                }
            }
        }
        return null;
    }

    public static Object toBean(TemplateModel templateModel) throws TemplateModelException {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateSequenceModel) {
                toBean(((TemplateSequenceModel) templateModel).get(0));
            }
            if (templateModel instanceof BeanModel) {
                return ((BeanModel) templateModel).getWrappedObject();
            }
        }
        return null;
    }


    public static Object toDate(TemplateModel templateModel) throws TemplateModelException {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateDateModel) {
              return ((TemplateDateModel) templateModel).getAsDate();
            }
        }
        return null;
    }

    public static String[] toStringArray(TemplateModel templateModel) throws TemplateModelException {
        if (templateModel instanceof TemplateSequenceModel) {
            TemplateSequenceModel sequenceModel = (TemplateSequenceModel) templateModel;
            String[] values = new String[sequenceModel.size()];
            for (int i = 0; i < sequenceModel.size(); i++) {
                values[i] = toString(sequenceModel.get(i));
            }
            return values;
        }
        return null;
    }


    public static Integer[] toIntegerArray(TemplateModel templateModel) throws TemplateModelException {
        String[] arr = toStringArray(templateModel);
        if (Checker.BeNotEmpty(arr)) {
            List<Integer> list = new ArrayList<>();
            for (String str : arr) {
                if(Checker.BeNotBlank(str)){
                    list.add(Integer.valueOf(str));
                }
            }
            return list.toArray(new Integer[list.size()]);
        }
        return null;
    }


    public static Long[] toLongArray(TemplateModel templateModel) throws TemplateModelException {
        String[] arr = toStringArray(templateModel);
        if (Checker.BeNotEmpty(arr)) {
            List<Long> list = new ArrayList<>();
            for (String str : arr) {
                if(Checker.BeNotBlank(str)){
                    list.add(Long.valueOf(str));
                }
            }
            return list.toArray(new Long[list.size()]);
        }
        return null;
    }

    public static TemplateHashModelEx toMap(TemplateModel templateModel)  {
        if (Checker.BeNotNull(templateModel)) {
            if (templateModel instanceof TemplateHashModelEx) {
                return (TemplateHashModelEx) templateModel;
            }
        }
        return null;
    }
}
